<template>
  <div style="border: 1px solid #ccc">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editorRef"
      :default-config="toolbarConfig"
    />
    <Editor
      v-model="value"
      :style="{ overflow: 'hidden', height: '500px', ...editorStyle }"
      :default-config="editorConfig"
      @on-created="handleCreated"
      @on-change="handleChange"
      @on-focus="$emit('on-focus')"
    />
  </div>
</template>

<script setup>
import { onBeforeUnmount, shallowRef } from 'vue'
import { TOOLBAR_KEYS } from '@/constant'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { getToken } from '@/utils'

import videoImg from '../../assets/images/video-placehold.png'
/* 参考：
https://www.wangeditor.com/v5/plugins.html
https://github.com/wangeditor-team/wangEditor-plugin-upload-attachment


*/

const value = defineModel('value', {
  type: String,
  default: '',
})
defineProps({
  editorStyle: {
    type: Object,
    default: null,
  },
})

const emit = defineEmits(['update:value', 'on-focus'])

const toolbarConfig = {
  toolbarKeys: TOOLBAR_KEYS,
}

const editorConfig = {
  placeholder: '请输入内容...',
  // 在编辑器中，点击选中“附件”节点时，要弹出的菜单
  hoverbarKeys: {
    attachment: {
      menuKeys: ['downloadAttachment'], // “下载附件”菜单
    },
  },

  MENU_CONF: {
    codeSelectLang: {
      codeLangs: [
        { text: 'C', value: 'c' },
        { text: 'C++', value: 'c++' }, //不支持c++高亮
        { text: 'Java', value: 'java' },
        // { text: 'Python', value: 'python' },
      ],
    },

    uploadImage: {
      server: '/api/uploadImgVideo/img',

      // form-data fieldName ，默认值 'wangeditor-uploaded-image'
      fieldName: 'file',
      // 单个文件的最大体积限制，默认为 2M
      maxFileSize: 2 * 1024 * 1024, // 2M
      // 最多可上传几个文件，默认为 100
      maxNumberOfFiles: 10,
      // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
      allowedFileTypes: ['image/*'],

      // 自定义增加 http  header
      headers: {
        Authorization: getToken(),
      },
      // 跨域是否传递 cookie ，默认为 false
      withCredentials: true,
      // 超时时间，默认为 10 秒
      timeout: 30 * 1000, // 30 秒
      // 自定义插入图跑
      customInsert(res, insertFn) {
        if (!res || !res.data) {
          return
        }
        const url = res.data
        insertFn(url, 'any', url)
      },
    },
    // 上传附件
    uploadAttachment: {
      server: '/api/uploadFile/upload', // 服务端地址
      timeout: 20 * 1000, // 20s
      fieldName: 'file',
      headers: { Authorization: getToken() },
      maxFileSize: 2 * 1024 * 1024, // 2M

      // onBeforeUpload(file) {
      //   console.log('onBeforeUpload', file)
      //   return file // 上传 file 文件
      //   // return false // 会阻止上传
      // },
      // onProgress(progress) {
      //   console.log('onProgress', progress)
      // },
      // 上传成功后，用户自定义插入文件
      customInsert(res, file, insertFn) {
        if (!res || !res.data) {
          return
        }
        const url = res.data
        // 插入附件到编辑器
        insertFn(file.name, url)
      },
    },
    // 上传视频
    uploadVideo: {
      server: '/api/uploadImgVideo/video',
      timeout: 120 * 1000, // 120秒
      fieldName: 'file',
      maxFileSize: 20 * 1024 * 1024, // 20M
      // 最多可上传几个文件，默认为 5
      maxNumberOfFiles: 3,
      // 选择文件时的类型限制，默认为 ['video/*'] 。如不想限制，则设置为 []
      allowedFileTypes: ['video/*'],
      // 自定义增加 http  header
      headers: {
        Authorization: getToken(),
      },
      // 跨域是否传递 cookie ，默认为 false
      withCredentials: true,

      // 上传进度的回调函数
      onProgress(progress) {
        // progress 是 0-100 的数字
        // console.log('progress', progress)
      },

      customInsert(res, insertFn) {
        try {
          if (!res || !res.data) {
            return
          }
          const { url } = res.data
          // 从 res 中找到 url poster ，然后插入视频
          insertFn(url, videoImg)
        } catch (err) {
          console.log(err)
        }
      },
    },
  },
}

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef()
const handleCreated = (editor) => {
  editorRef.value = editor // 记录 editor 实例，重要！
}

const handleChange = (newVal) => {
  emit('update:value', newVal.getHtml())
}

onBeforeUnmount(() => {
  // 销毁编辑器
  editorRef.value?.destroy()
})
</script>

<style>
.w-e-text-container [data-slate-editor] p {
  margin: 0 0;
}
.w-e-text-placeholder {
  font-style: italic;
  left: 10px;
  top: 10px;
  width: 90%;
}
.w-e-text-container [data-slate-editor] {
  word-wrap: break-word;
  border-top: 1px solid transparent;
  min-height: 100%;
  outline: 0;
  padding: 10px 10px;
  white-space: pre-wrap;
}
</style>
